#include "glare.d3d11.ShaderInterface.h"
#include "Glare.Core.Driver.h"

namespace Glare {

	void D3D11ShaderInterface::InitializeConstantBuffers(D3D11ShaderInterface* shader_interface, Shader* shader)
	{
		Driver* driver = shader_interface->GetDriver();

		ID3DBlob* bytecode = shader_interface->GetD3DByteCode();

		ID3D11ShaderReflection* reflection = NULL;

		GLARE_THROW(D3DReflect(
			bytecode->GetBufferPointer(),
			bytecode->GetBufferSize(), 
			IID_ID3D11ShaderReflection,
			(void**)&reflection), "error while reading D3D11 shader metadata");

		if (reflection)
		{
			D3D11_SHADER_DESC shader_desc;
			reflection->GetDesc(&shader_desc);

			for (uint cbi = 0; cbi < shader_desc.ConstantBuffers; ++cbi)
			{
				ID3D11ShaderReflectionConstantBuffer* cb = reflection->GetConstantBufferByIndex(cbi);

				D3D11_SHADER_BUFFER_DESC sb_desc;
				cb->GetDesc(&sb_desc);

				ConstantBufferDescription cbd;

				for (uint svi = 0; svi < sb_desc.Variables; ++svi)
				{
					ID3D11ShaderReflectionVariable* sv = cb->GetVariableByIndex(svi);

					D3D11_SHADER_VARIABLE_DESC sv_desc;
					sv->GetDesc(&sv_desc);

					ShaderVariableDescription svd;
					svd.DefaultValue = sv_desc.DefaultValue;
					svd.Flags = sv_desc.uFlags;
					svd.Name = sv_desc.Name;
					svd.SamplerCount = sv_desc.SamplerSize;
					svd.Size = sv_desc.Size;
					svd.StartOffset = sv_desc.StartOffset;
					svd.StartSampler = sv_desc.StartSampler;
					svd.StartTexture = sv_desc.StartTexture;
					svd.TextureCount = sv_desc.TextureSize;

					cbd.AddVariable(svd);
				}

				shader->_AddConstantBufferDescription(cbd);
			}

			GLARE_SAFE_RELEASE(reflection, "Error while releasing D3D11 shader reflection");
		}
		else
			driver->WriteLog("Unable to get constant buffer information from D3D11 shader", LMT_Warning);
	}
}
